import pygame
import sys
import cv2
sys.path.append('game_custom')
from random import choice
from game_custom.player import Player,global_value
from game_custom.endplayer import EndPlayer
from game_custom.obstacle import Obstacle
from game_custom.setting import *
from game_custom.bullet import Bullet
from game_custom.hand_tracking import HandTracking
#设置帧数
FPS = 60
class Runner:
    def __init__(self):
        pygame.init()
        self.setting = Settings()
        #屏幕宽高
        self.width = SCREEN_WIDTH
        self.height = SCREEN_HEIGHT

        #字体样式
        self.font = self.setting.font

        #屏幕放置
        self.screen = pygame.display.set_mode(
            (self.width,self.height))
        
        #背景 需要先放置屏幕再使用convert()
        self.background = self.setting.background.convert()
        self.background = pygame.transform.scale(self.background,(self.width,self.height - 168))

        #地面
        self.floor = self.setting.floor.convert()
        self.floor = pygame.transform.scale(self.floor,(self.width,self.height - 168))

        #限制帧数
        self.clock = pygame.time.Clock()

        #音乐
        self.bgm = self.setting.bg_music
        pygame.mixer.music.play(-1,0)
        pygame.mixer.music.set_volume(0.05)

        #消灭怪物的声音
        self.blt_col_obs = pygame.mixer.Sound('game_custom/video/collide.mp3')
        self.blt_col_obs.set_volume(0.15)
        #结束声音
        self.end_sound = pygame.mixer.Sound('game_custom/video/end.mp3')
        self.end_sound.set_volume(0.15)

        #游戏状态
        self.game_active = False
        #分数
        self.start_time = 0
        self.score = 0

        #游戏结算时的显示
        #游戏名
        self.game_name = self.font.render('来和坤坤消灭怪物吧！',False,(111,196,169))
        #游戏信息
        self.game_message = self.font.render('按下空格键开始与坤坤作战！',False,(111,196,169))
        self.control_message = self.font.render('操作提示：左手闭合控制跳跃，右手闭合控制篮球的发射',False,(111,196,169))
        self.ps = self.font.render('PS：坤坤只可发射一个篮球，任何情况下都可以按下ESC退出游戏！',False,(111,196,169))
        self.start = self.font.render("开始游戏",False,(111,196,169))
        self.quit = self.font.render("退出游戏",False,(111,196,169))

        #游戏名矩形
        self.game_name_rect = self.game_name.get_rect(
            center = (self.width//2 - 5, self.height//2 - 120))
        #游戏信息矩形
        self.game_message_rect = self.game_message.get_rect(
            center = (self.width//2 - 10, self.height//2 + 120))
        self.control_message_rect = self.control_message.get_rect(
            center = (self.width//2 - 10,self.height//2 + 160)
        )
        self.ps_rect = self.ps.get_rect(
            center = (self.width//2 - 10,self.height//2 + 200)
        )
        self.start_rect = self.start.get_rect(
            center = (self.width//2 - 10,self.height//2 + 240)
        )
        self.quit_rect = self.quit.get_rect(
            center = (self.width//2 - 10,self.height//2 + 280)
        )
        #标题
        pygame.display.set_caption("和坤坤并肩作战")

        #获取摄像头 防止关闭出错
        self.cap = cv2.VideoCapture(0)
        #创建手势跟踪实例
        self.hand_tracking = HandTracking()
        
        #玩家
        self.player = pygame.sprite.GroupSingle()
        self.player.add(Player())
        #结算时的玩家
        self.end_player = pygame.sprite.GroupSingle()
        self.end_player.add(EndPlayer())
        #子弹
        self.blt = pygame.sprite.Group()
        #障碍
        self.obstacle_group = pygame.sprite.Group()
        self.obstacle_timer = pygame.USEREVENT + 1
        #生成障碍物事件的时间
        pygame.time.set_timer(self.obstacle_timer,900)
    
    def run_game(self):
        while True:
            #读取事件
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
                #游戏运行时
                if self.game_active:
                    #生成怪物
                    if event.type == self.obstacle_timer:
                        self.obstacle_group.add(Obstacle(choice(['bone','fly','bigmonster','ghost','animal','lmonster'])))
                    if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                        self.cap.release()
                        cv2.destroyAllWindows()
                        sys.exit()
                #游戏未运行时
                else:
                    #鼠标
                    self.mouse = pygame.mouse.get_pos()
                    #按下空格开始游戏
                    if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                        #设置游戏状态
                        self.game_active = True
                        #用于计算分数
                        self.start_time = pygame.time.get_ticks() // 1000
                    #游戏结束关闭摄像头画面
                    if self.cap.isOpened():
                        cv2.destroyAllWindows()
                    #ESC键退出游戏
                    if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                        self.cap.release()
                        cv2.destroyAllWindows()
                        sys.exit()
                    if event.type == pygame.MOUSEBUTTONDOWN:
                        if self.width//2-80 <= self.mouse[0] <= self.width//2+80 and self.height//2+220 <= self.mouse[1] <= self.height//2+260:
                            self.game_active = True
                        if self.width//2-80 <= self.mouse[0] <= self.width//2+80 and self.height//2+260 <= self.mouse[1] <= self.height//2+300:
                            self.cap.release()
                            cv2.destroyAllWindows()
                            sys.exit()
            #游戏运行时
            if self.game_active:
                #载入摄像头
                self.load_cap()
                #手势检测
                self.scan_hand()
                #语音识别
                #判断右手是否闭合
                self.hand_right_close = self.hand_tracking.hand_right_close
                self.hand_left_close = self.hand_tracking.hand_left_close
                if self.hand_right_close:
                    if len(self.blt) < 1:
                        new_blt = Bullet()
                        self.blt.add(new_blt)
                if self.hand_left_close:
                    global_value.JUMP = True
                else:
                    global_value.JUMP = False
                #放置背景
                self.screen.blit(self.background,(0,0))
                #放置地面
                self.screen.blit(self.floor,(0,812))
                #获取分数
                self.score = self.display_score()
                #通过精灵的image和rect绘制
                '''加载玩家，子弹，怪物'''
                self.player.draw(self.screen)
                self.player.update()
                self.blt.draw(self.screen)
                self.update_blt()
                self.obstacle_group.draw(self.screen)
                self.obstacle_group.update()
                #检测到碰撞更新游戏状态
                self.game_active = self.collision_sprite()
                cv2.imshow('frame',self.frame)
                k = cv2.waitKey(1)
                #esc退出游戏
                if k & 0xff == 27:
                    self.cap.release()
                    cv2.destroyAllWindows()
                    sys.exit()
            else:
                #结算的背景
                self.screen.fill((94,129,162))
                #结算分数
                score_message = self.font.render(f'分数:{self.score}',False,(111,196,169))
                #结算分数矩形
                score_message_rect = score_message.get_rect(
                    center=(self.width//2 - 20, self.height//2 + 120))
                #结算时的玩家动画
                self.end_player.draw(self.screen)
                self.end_player.update()
                #开始游戏按钮的鼠标悬浮反馈
                if self.width//2-80 <= self.mouse[0] <= self.width//2+80 and self.height//2+220 <= self.mouse[1] <= self.height//2+260:
                    pygame.draw.rect(self.screen,(170,170,170),[self.width//2-80,self.height//2+220,140,40])
                else:
                    pygame.draw.rect(self.screen,(100,100,100),[self.width//2-80,self.height//2+220,140,40])
                #退出游戏按钮的鼠标悬浮反馈
                if self.width//2-80 <= self.mouse[0] <= self.width//2+80 and self.height//2+260 <= self.mouse[1] <= self.height//2+300:
                    pygame.draw.rect(self.screen,(170,170,170),[self.width//2-80,self.height//2+260,140,40])
                else:
                    pygame.draw.rect(self.screen,(100,100,100),[self.width//2-80,self.height//2+260,140,40])
                #游戏信息
                self.screen.blit(self.game_name,self.game_name_rect)
                self.screen.blit(self.control_message,self.control_message_rect)
                self.screen.blit(self.ps,self.ps_rect)
                self.screen.blit(self.start,self.start_rect)
                self.screen.blit(self.quit,self.quit_rect)
                if self.score == 0:
                    self.screen.blit(self.game_message,self.game_message_rect)
                else:
                    self.screen.blit(score_message,score_message_rect)
            #更新整个surface
            pygame.display.flip()
            #设置帧速率 没有限制帧数就太快
            self.clock.tick(FPS)
    #检测玩家与障碍物碰撞
    def collision_sprite(self):
        if pygame.sprite.spritecollide(self.player.sprite,self.obstacle_group,False):
            #播放结束音
            self.end_sound.play()
            #清空障碍物
            self.obstacle_group.empty()
            #清空子弹
            self.blt.empty()
            #返回游戏运行状态
            return False
        else:
            return True

    def display_score(self):
        #以存活时间来决定分数
        current_time = (pygame.time.get_ticks() // 1000) - self.start_time
        #放置分数
        score_surface = self.font.render(f'分数:{current_time}',False,(255,124,124))
        score_rect = score_surface.get_rect(center=(100,20))
        self.screen.blit(score_surface,score_rect)
        #放置篮球信息
        blt_num_surface = self.font.render(f'篮球数：{len(self.blt)}',False,(255,124,124))
        blt_num_rect = blt_num_surface.get_rect(center = (100,600))
        self.screen.blit(blt_num_surface,blt_num_rect)
        return current_time
    
    #检测子弹和障碍物的碰撞
    def check_blt_obs_collisions(self):
        pygame.sprite.groupcollide(self.blt,self.obstacle_group,True,True)
        
    #绘制篮球
    def update_blt(self):
        self.blt.update()
        for bullet in self.blt.copy():
            if bullet.rect.right >= 1440:
                self.blt.remove(bullet)
        self.check_blt_obs_collisions()

    #加载摄像头
    def load_cap(self):
        _,self.frame = self.cap.read()

    #检测手势
    def scan_hand(self):
        self.frame = self.hand_tracking.scan_hands(self.frame)


if __name__ == '__main__':
    rn = Runner()
    rn.run_game()